package com.sq.util.command;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.CountDownLatch;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sq.util.IOUtil;

/**
 * 
 * 注意这个不能多线程执行，有可能会丢失返回结果
 *
 */
public class CommandUtil {

    protected static final Logger log = LoggerFactory.getLogger(CommandUtil.class);

    private final static byte[] lock = new byte[1];

    public static CommandResult runShell(String cmd, String charsetName) throws Exception {
        log.info("执行命令" + cmd);
        String[] cmds = { "/bin/sh", "-c", cmd };
        return run(cmds, charsetName);
    }

    public static CommandResult runCmd(String cmd, String charsetName) throws Exception {
        log.info("执行命令" + cmd);
        String[] cmds = { "cmd", "/c", cmd };
        return run(cmds, charsetName);
    }

    private static CommandResult run(String[] cmds, String charsetName) throws Exception {
        synchronized (lock) {
            return _run(cmds, charsetName);
        }
    }

    private static CommandResult _run(String[] cmds, String charsetName) throws IOException, InterruptedException {
        Process p = Runtime.getRuntime().exec(cmds);
        CommandResult commandResult = new CommandResult();
        CountDownLatch latch = new CountDownLatch(2);
        new Thread() {
            public void run() {
                StringBuilder sb = new StringBuilder(128);
                String line = null;
                InputStreamReader isr = null;
                BufferedReader br = null;
                InputStream input = p.getInputStream();
                try {
                    isr = new InputStreamReader(input, charsetName);
                    br = new BufferedReader(isr);
                    while ((line = br.readLine()) != null) {
                        sb.append(line).append("\n");
                    }
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                } finally {
                    commandResult.setResult(sb.toString());
                    IOUtil.closeQuietly(br);
                    IOUtil.closeQuietly(isr);
                    IOUtil.closeQuietly(input);
                    latch.countDown();
                }
            }
        }.start();

        new Thread() {
            public void run() {
                StringBuilder sb = new StringBuilder(64);
                String line = null;
                InputStreamReader isr = null;
                BufferedReader br = null;
                InputStream input = p.getErrorStream();
                try {
                    isr = new InputStreamReader(input, charsetName);
                    br = new BufferedReader(isr);
                    while ((line = br.readLine()) != null) {
                        sb.append(line).append("\n");
                    }
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                } finally {
                    commandResult.setErrorMsg(sb.toString());
                    IOUtil.closeQuietly(br);
                    IOUtil.closeQuietly(isr);
                    IOUtil.closeQuietly(input);
                    latch.countDown();
                }
            }
        }.start();
        commandResult.setCode(p.waitFor());
        latch.await();
        return commandResult;
    }
}